﻿using System;
using System.Globalization;
using System.Windows.Forms;
using Business;
using Business.Dicionary;
using Business.Entity.Contabil.Pessoa;
using Business.Entity.Contabil.Pessoa.SubClass.Usuario.ClassesRelacionadas;
using Business.Entity.Estoque.Produto;
using Business.Entity.Fiscal;
using Business.Entity.Fiscal.ClassesRelacionadas;
using Business.Entity.Sped.ClassesRelacionadas;
using Business.Enum;
using Business.Forms;
using Business.Seguranca;
using Business.Validation;
using DevExpress.XtraEditors;

namespace Bonesoft.Forms.Fiscal
{
    public partial class FormNotaFiscalSaida : FormDefault, IForm
    {
        public TipoBuscaProduto TipoBusca { get; set; }
        public Produto ProdutoSelecionado { get; set; }
        public FormNotaFiscalSaida()
        {
            InitializeComponent();
            notaFiscalBindingSource.DataSource = new NotaFiscal();
            valorTextEdit.LostFocus += valorTextEdit_LostFocus;
            descricaoTextEdit.LostFocus += descricaoTextEdit_LostFocus;
            freteSpinEdit.LostFocus += freteSpinEdit_LostFocus;
            seguroSpinEdit.LostFocus += freteSpinEdit_LostFocus;
            descontoSpinEdit.LostFocus += freteSpinEdit_LostFocus;
            outrasDespesasAcessoriasSpinEdit.LostFocus += freteSpinEdit_LostFocus;

            TipoBusca = TipoBuscaProduto.Descricao;

            // Carga dos campos a serem preenchidos.
            var pessoas = NotaFiscalRepository.GetSession().CreateCriteria<Pessoa>().List();
            destinatarioBindingSource.DataSource = pessoas;
            transportadoraBindingSource.DataSource = pessoas;
            naturezaInternaBindingSource.DataSource = NotaFiscalRepository.GetSession()
                .CreateCriteria<NaturezaInterna>().List();
            modeloNotaFiscalDicionaryBindingSource.DataSource = new ModeloNotaFiscalDicionary();
            CalculaNota();
        }

        private void freteSpinEdit_LostFocus(object sender, EventArgs e)
        {
            CalculaNota();
        }

        private void descricaoTextEdit_LostFocus(object sender, EventArgs e)
        {

            switch (TipoBusca)
            {
                case TipoBuscaProduto.Descricao:
                    ProdutoSelecionado = WindowsControls.Utils.Functions.SelecionaProduto(ProdutoRepository.GetByDescricao(descricaoTextEdit.Text));
                    break;
                case TipoBuscaProduto.CodBarra:
                    ProdutoSelecionado = WindowsControls.Utils.Functions.SelecionaProduto(ProdutoRepository.GetByCodBarra(descricaoTextEdit.Text));
                    break;
                case TipoBuscaProduto.Referencia:
                    ProdutoSelecionado = WindowsControls.Utils.Functions.SelecionaProduto(ProdutoRepository.GetByReferencia(descricaoTextEdit.Text));
                    break;
            }
            if (ProdutoSelecionado != null)
            {
                descricaoTextEdit.Text = ProdutoSelecionado.Descricao;
                quantidadeTextEdit.Focus();
                quantidadeTextEdit.SelectAll();
            }
            else
            {
                freteSpinEdit.Focus();
            }

        }

        private void valorTextEdit_LostFocus(object sender, EventArgs e)
        {
            var trib = TributacaoNcmEstadoRepository.GetTributacaoNcmEstadoByTributacaoNcm(
                Utils.Terminal.Empresa.Pessoa.Enderecos[0].Endereco.Cidade.Estado.Id,
                ProdutoSelecionado.NCM.Tributacao);
            if (ProdutoSelecionado != null)
            {
                var prod = new ProdutoNotaFiscal();
                prod.Sequencia += produtosBindingSource.Count + 1;
                prod.Produto = ProdutoSelecionado;
                prod.NCM = ProdutoSelecionado.NCM;
                prod.ValorUnitario = decimal.Parse(valorTextEdit.EditValue.ToString());
                prod.TipoOperacaoNotaDaGente = trib.OpercaoNotaDaGente;

            }
            descricaoTextEdit.Focus();
            CalculaNota();
        }

        private void descricaoTextEdit_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.KeyData)
            {
                case Keys.Up:
                    produtosBindingSource.MovePrevious();
                    ExibeProduto();
                    break;
                case Keys.Down:
                    produtosBindingSource.MoveNext();
                    ExibeProduto();
                    break;
                case Keys.Escape:
                    LimparProdutoExibido();
                    break;
                case Keys.Delete:
                    ExcluirProduto();
                    break;
            }
        }

        private void ExcluirProduto()
        {
            int cont = 1;
            if (!sequenciaTextEdit.Text.Equals(""))
            {
                produtosBindingSource.RemoveAt((int)sequenciaTextEdit.EditValue);
            }
            foreach (ProdutoNotaFiscal prod in produtosBindingSource)
            {
                prod.Sequencia = cont;
            }
            CalculaNota();
        }

        private void LimparProdutoExibido()
        {
            sequenciaTextEdit.Text = "";
            descricaoTextEdit.Text = "";
            quantidadeTextEdit.Text = "";
            valorTextEdit.Text = "";
            ProdutoSelecionado = null;
        }

        private void ExibeProduto()
        {
            if (CurrentObject == null)
            {
                return;
            }
            var p = (ProdutoNotaFiscal)produtosBindingSource.Current;
            seguroSpinEdit.Value = p.Sequencia;
            descricaoTextEdit.Text = p.Produto.Descricao;
            quantidadeTextEdit.Text = p.Quantidade.ToString(CultureInfo.InvariantCulture);
            valorTextEdit.Text = p.ValorUnitario.ToString(CultureInfo.InvariantCulture);
            ProdutoSelecionado = p.Produto;
            CalculaNota();
        }

        private void CalculaNota()
        {
            if (CurrentObject == null)
            {
                return;
            }
            decimal total = 0;
            var n = (NotaFiscal)CurrentObject;
            foreach (ProdutoNotaFiscal prod in produtosBindingSource)
            {
                total += prod.ValorUnitario * prod.Quantidade;
            }
            total += n.Frete + n.OutrasDespesasAcessorias + n.Seguro - n.Desconto;
            totalTextEdit.Value = total;
        }

        private void valorTextEdit_Enter(object sender, EventArgs e)
        {
            valorTextEdit.SelectAll();

        }

        public object Novo()
        {
            var n = new NotaFiscal();
            CurrentObject = n;
            CalculaNota();
            ShowDialog();
            if (n.Id == 0)
            {
                return null;
            }
            return n;
        }

        public void Alterar(object entity)
        {
            CurrentObject = entity;
            CalculaNota();
            ShowDialog();
        }

        
        public object Save()
        {
            if (!Validate().HasError)
            {
                NotaFiscalRepository.Save((NotaFiscal) CurrentObject);
            }
            return CurrentObject;
        }

        public void Update(object entity)
        {
            Alterar(entity);
        }

        public bool Delete(object entity)
        {
            CurrentObject = entity;
            NotaFiscalRepository.Delete((NotaFiscal) entity);
            return true;
        }

        public object CurrentObject
        {
            get
            {
                notaFiscalBindingSource.EndEdit();
                return notaFiscalBindingSource.DataSource;
            }
            set
            {
                notaFiscalBindingSource.DataSource = value;
            }
        }

        public PermissaoForm Permissao
        {
            get
            {
                return SegurancaUtils.GetPermissaoForm(Name);
            }
        }

        public EntityValidationResult Validate()
        {
            var nf = (NotaFiscal) CurrentObject;
            var result = DataValidation.ValidateEntity(nf);
            foreach (var prod in nf.Produtos)
            {
                foreach (var error in DataValidation.ValidateEntity(prod).ValidationErrors)
                {
                    result.ValidationErrors.Add(error);
                }
            }
            return result;
        }

        public void Reload()
        {
            
        }

        public void Cancel()
        {
            DialogResult = DialogResult.Cancel;
            Close();
        }

        public Object New()
        {
            return Novo();
        }

        public XtraForm Form
        {
            get
            {
                return this;
            }
        }

        public FormState FormState { get; set; }
    }
}